﻿using System;
using System.Collections.Specialized;
using System.Globalization;
using System.Web;
using System.Web.Mvc;
using System.Xml;

namespace BitworkStudios.Web.Mvc.Framework.SiteMap.Providers
{
    public abstract class SiteMapProviderBase : StaticSiteMapProvider, ISiteMapProvider
    {
        private const String SiteMapNodeName = "siteMapNode";
        protected SiteMapNode _rootNode = null;

        public XmlDocument SiteMapXml { get; set; }

        public new SiteMapNode RootNode
        {
            get { return BuildSiteMap(); }
        }

        public abstract override SiteMapNode BuildSiteMap();
        protected new abstract void Initialize(string name, NameValueCollection attributes);

        public new void Clear()
        {
            lock (this)
            {
                _rootNode = null;
                base.Clear();
            }
        }

        protected SiteMapNode GetSiteMapNodeFromElement(XmlElement rootElement)
        {
            String title = rootElement.GetAttribute("title");
            String action = rootElement.GetAttribute("action");
            String controller = rootElement.GetAttribute("controller");
            String description = rootElement.GetAttribute("description");

            // The key needs to be unique, so hash the url and title.
            var url = new UrlHelper(HttpContext.Current.Request.RequestContext);
            string urlString = url.Action(action, controller);
            var newSiteMapNode = new SiteMapNode(this, urlString.GetHashCode().ToString(CultureInfo.InvariantCulture), urlString, title, description);

            return newSiteMapNode;
        }

        protected void GenerateSiteMapNodes(XmlElement rootElement)
        {
            _rootNode = GetSiteMapNodeFromElement(rootElement);
            AddNode(_rootNode);
            CreateChildNodes(rootElement, _rootNode);
        }

        protected void CreateChildNodes(XmlElement parentElement, SiteMapNode parentNode)
        {
            foreach (XmlNode xmlElement in parentElement.ChildNodes)
            {
                if (xmlElement.Name == SiteMapNodeName)
                {
                    SiteMapNode childNode = GetSiteMapNodeFromElement((XmlElement)xmlElement);
                    AddNode(childNode, parentNode);
                    CreateChildNodes((XmlElement)xmlElement, childNode);
                }
            }
        }
    }
}
